package com.lovejoanlyn.core;

import android.net.Uri;
import android.util.Log;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.net.ssl.HttpsURLConnection;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;

public class HttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {

    private static final String TAG = "HttpServerHandler";

    private String mCacheDir;

    private final DateFormat df2 = DateFormat.getDateInstance(DateFormat.FULL, Locale.CHINA);

//    private String[] adddress = {
//            "http://192.168.17.86:8081/repository/maven-public",
//            "https://maven.aliyun.com/repository/jcenter",
//            "https://maven.aliyun.com/repository/google"
//    };

    private List<String> mRepositories = new ArrayList<>();

    public HttpServerHandler(List<String> repositories){
        try {
            mCacheDir = File.createTempFile("nexus", "android")
                    .getParentFile().getAbsolutePath();
            mRepositories.addAll(repositories);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        if (!(msg instanceof FullHttpRequest)) {
            Log.e(TAG, "未知请求：" + msg.toString());
            return;
        }
        FullHttpRequest httpRequest = (FullHttpRequest) msg;
        String path = httpRequest.uri();
        HttpMethod method = httpRequest.method();

        if (method != HttpMethod.GET && method != HttpMethod.HEAD) {
            ByteBuf byteBuf = Unpooled.copiedBuffer("不支持的请求方式".getBytes());
            response(ctx, "text/json;charset=UTF-8", byteBuf, HttpResponseStatus.BAD_REQUEST);
            return;
        }

        Log.e(TAG, "******************接收到了请求******************");
        Log.e(TAG, "method:" + method);
        Log.e(TAG, "route:" + path);

        ByteBuf imgBuf = null;
        for(int i = 0; i < mRepositories.size(); i++) {
           imgBuf = getFile(path, mRepositories.get(i));
           if(imgBuf != null) {
               if (method == HttpMethod.GET) {
                   response(ctx, "application/octet-stream", imgBuf, HttpResponseStatus.OK);
               } else {
                   responseHead(ctx, "application/octet-stream", HttpResponseStatus.OK);
               }
               return;
           }
        }

        response(ctx, "text/json;charset=UTF-8", HttpResponseStatus.NOT_FOUND);
    }

    private synchronized ByteBuf getFile(String path, String serverAddress){
        try {
            File local = new File(mCacheDir + path);
            ByteBuf byteBuf = Unpooled.buffer();
            InputStream fileInputStream = null;
            OutputStream fileOutputStream = null;
            try {
                if (local.exists()) {
                    Log.v(TAG, "使用离线缓存:" + local.getAbsolutePath());
                    fileInputStream = new FileInputStream(local);
                } else {
                    Log.v(TAG, "下载: " + serverAddress + path);
                    URL url = new URL(serverAddress + path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    // 设置连接超时为5秒
                    conn.setConnectTimeout(5000);
                    // 设置请求类型为Get类型
                    conn.setRequestMethod("GET");
                    // 判断请求Url是否成功
                    if (conn.getResponseCode() != 200) {
                        throw new IOException("请求url失败: " + serverAddress + path);
                    }
                    fileInputStream = conn.getInputStream();

                    // 缓存文件
                    boolean ret = local.getParentFile().mkdirs();
                    if (ret) {
                        fileOutputStream = new FileOutputStream(local);
                    }
                }

                int len;
                byte[] buf = new byte[1024];
                while ((len = fileInputStream.read(buf)) != -1) {
                    byteBuf.writeBytes(buf, 0, len);
                    if (fileOutputStream != null) {
                        fileOutputStream.write(buf, 0, len);
                    }
                }
            } finally {

                if (fileInputStream != null) {
                    fileInputStream.close();
                    fileInputStream = null;
                }

                if (fileOutputStream != null) {
                    fileOutputStream.close();
                    fileOutputStream = null;
                }

            }

            return byteBuf;
        }catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }


    private void response(ChannelHandlerContext ctx, String type, HttpResponseStatus status) {
        FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status);
        httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, type);
        httpResponse.headers().set(HttpHeaderNames.CONNECTION, "keep-alive");
        //httpResponse.headers().set(HttpHeaderNames.CONNECTION, "keep-alive");
        ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);
    }

    private void response(ChannelHandlerContext ctx, String type, ByteBuf byteBuf, HttpResponseStatus status) {
        FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, byteBuf);
        httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, type);
        httpResponse.headers().set(HttpHeaderNames.CONNECTION, "keep-alive");
        httpResponse.headers().set(HttpHeaderNames.ACCEPT_RANGES, "bytes");
        httpResponse.headers().set(HttpHeaderNames.DATE, df2.format(new Date()));
        httpResponse.headers().set(HttpHeaderNames.ETAG, System.currentTimeMillis() + "");
        httpResponse.headers().set(HttpHeaderNames.SERVER ,"Nexus/3.37.3-02 (OSS)");
        httpResponse.headers().set(HttpHeaderNames.CONTENT_DISPOSITION ,"inline");
        httpResponse.headers().set("Content-Security-Policy",
        "sandbox allow-forms allow-modals allow-popups allow-presentation allow-scripts allow-top-navigation");
        ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);
    }

    private void responseHead(ChannelHandlerContext ctx, String type, HttpResponseStatus status) {
        FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status);
        httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, type);
        httpResponse.headers().set(HttpHeaderNames.CONNECTION, "keep-alive");
        httpResponse.headers().set(HttpHeaderNames.ACCEPT_RANGES, "bytes");
        httpResponse.headers().set(HttpHeaderNames.DATE, df2.format(new Date()));
        httpResponse.headers().set(HttpHeaderNames.ETAG, System.currentTimeMillis() + "");
        httpResponse.headers().set(HttpHeaderNames.SERVER ,"Nexus/3.37.3-02 (OSS)");
        httpResponse.headers().set(HttpHeaderNames.CONTENT_DISPOSITION ,"inline");
        httpResponse.headers().set("Content-Security-Policy",
                "sandbox allow-forms allow-modals allow-popups allow-presentation allow-scripts allow-top-navigation");
        ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);
    }


}